﻿using System;
using System.Text;

namespace MyFastORM
{
    /// <summary>
    /// 数据操作帮助类的基础类型
    /// </summary>
    /// <remarks>
    /// 快速ORM框架会使用该类型作为所有动态生成的数据处理帮助类的统一的接口，因此所有动态
    /// 生成的数据帮助类都是从该类派生的。该类型中的所有的 abstract 修饰的成员都是需要在派生
    /// 类中实现，而 protected 修饰的成员都会在派生类中调用。
    /// 编写 袁永福
    /// </remarks>
    public abstract class RecordORMHelper
    {
        /// <summary>
        /// 对象操作的数据表名称
        /// </summary>
        public abstract string TableName
        {
            get;
        }

        /// <summary>
        /// 字段列表数组
        /// </summary>
        protected abstract string[] RecordFieldNames
        {
            get;
        }

        /// <summary>
        /// 从数据读取器读取数据创建一个记录对象
        /// </summary>
        /// <param name="reader">数据读取器</param>
        /// <returns>读取的数据</returns>
        public object ReadRecord(System.Data.IDataReader reader)
        {
            int[] indexs = GetFieldIndexs(reader);
            return InnerReadRecord(reader, indexs);
        }

        /// <summary>
        /// 从数据读取器读取数据创建若干个记录对象
        /// </summary>
        /// <param name="reader">数据读取器</param>
        /// <param name="MaxRecordCount">允许读取的最大的记录个数，为0则无限制</param>
        /// <returns>读取的数据对象列表</returns>
        public System.Collections.ArrayList ReadRecords(
            System.Data.IDataReader reader,
            int MaxRecordCount)
        {
            System.Collections.ArrayList list = new System.Collections.ArrayList();
            int[] indexs = GetFieldIndexs(reader);
            while (reader.Read())
            {
                object record = InnerReadRecord(reader, indexs);
                list.Add(record);
                if (MaxRecordCount > 0 && list.Count >= MaxRecordCount)
                {
                    break;
                }
            }//while
            return list;
        }

        /// <summary>
        /// 从一个数据读取器中读取一条记录对象,必须重载
        /// </summary>
        /// <param name="reader">数据读取器</param>
        /// <param name="FieldIndexs">字段序号列表</param>
        /// <returns>读取的记录对象</returns>
        protected abstract object InnerReadRecord(
            System.Data.IDataReader reader,
            int[] FieldIndexs);


        /// <summary>
        /// 为删除记录而初始化数据库命令对象
        /// </summary>
        /// <param name="cmd">数据库命令对象</param>
        /// <param name="objRecord">实体对象实例</param>
        /// <returns>添加的SQL参数个数</returns>
        public abstract int FillDeleteCommand(
            System.Data.IDbCommand cmd,
            object objRecord);

        /// <summary>
        /// 为插入记录而初始化数据库命令对象
        /// </summary>
        /// <param name="cmd">数据库命令对象</param>
        /// <param name="objRecord">实体对象实例</param>
        /// <returns>添加的SQL参数个数</returns>
        public abstract int FillInsertCommand(
            System.Data.IDbCommand cmd,
            object objRecord);

        /// <summary>
        /// 为更新数据库记录而初始化数据库命令对象
        /// </summary>
        /// <param name="cmd">数据库命令对象</param>
        /// <param name="objRecord">实体对象实例</param>
        /// <returns>添加的SQL参数个数</returns>
        public abstract int FillUpdateCommand(
            System.Data.IDbCommand cmd,
            object objRecord);



        /// <summary>
        /// 针对特定的数据读取器获得实体对象的各个属性对应的数据栏目的编号
        /// </summary>
        /// <param name="reader">数据读取器</param>
        /// <returns>编号列表</returns>
        private int[] GetFieldIndexs(System.Data.IDataReader reader)
        {
            if (reader == null)
            {
                throw new ArgumentNullException("reader");
            }
            // 获得所有的字段名
            string[] FieldNames = this.RecordFieldNames;

            int[] indexs = new int[FieldNames.Length];
            int FieldCount = reader.FieldCount;
            // 获得数据读取器中所有的字段名
            string[] names = new string[FieldCount];
            for (int iCount = 0; iCount < FieldCount; iCount++)
            {
                names[iCount] = reader.GetName(iCount);
            }
            // 遍历数据读取器中所有的字段名，设置字段序号
            for (int iCount = 0; iCount < indexs.Length; iCount++)
            {
                indexs[iCount] = -1;
                string name = FieldNames[iCount];
                for (int iCount2 = 0; iCount2 < FieldCount; iCount2++)
                {
                    if (EqualsFieldName(name, names[iCount2]))
                    {
                        indexs[iCount] = iCount2;
                        break;
                    }
                }
            }
            // 获得一个字段序号数组，为了以后填充数据提高性能
            return indexs;
        }

        /// <summary>
        /// 连接多个字符串,各个字符串之间用逗号分隔，本函数会在动态生成的派生类中使用
        /// </summary>
        /// <param name="strs">字符串集合</param>
        /// <returns>连接所得的大字符串</returns>
        protected string ConcatStrings(System.Collections.IEnumerable strs)
        {
            System.Text.StringBuilder myStr = new System.Text.StringBuilder();
            foreach (string str in strs)
            {
                if (myStr.Length > 0)
                {
                    myStr.Append(",");
                }
                myStr.Append(str);
            }//foreach
            return myStr.ToString();
        }
        /// <summary>
        /// 判断两个字段名是否等价
        /// </summary>
        /// <param name="name1">字段名1</param>
        /// <param name="name2">字段名2</param>
        /// <returns>true:两个字段名等价 false:字段名不相同</returns>
        private bool EqualsFieldName(string name1, string name2)
        {
            if (name1 == null || name2 == null)
            {
                throw new ArgumentNullException("name1 or name2");
            }
            name1 = name1.Trim();
            name2 = name2.Trim();
            // 进行不区分大小写的比较
            if (string.Compare(name1, name2, true) == 0)
            {
                return true;
            }
            int index = name1.IndexOf(".");
            if (index > 0)
            {
                name1 = name1.Substring(index + 1).Trim();
            }
            index = name2.IndexOf(".");
            if (index > 0)
            {
                name2 = name2.Substring(index + 1).Trim();
            }
            return string.Compare(name1, name2, true) == 0;
        }

        #region 从数据库读取的原始数据转换为指定数据类型的函数群，本函数会在动态生成的派生类中使用

        /// <summary>
        /// 将从数据库获得的原始数据转换为字节数据，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected byte ConvertToByte(object v, byte DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToByte(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为带符号字节数据，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected sbyte ConvertToSByte(object v, sbyte DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToSByte(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为16位有符号整数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected short ConvertToInt16(object v, short DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToInt16(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为16位无符号整数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected ushort ConvertToUInt16(object v, ushort DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToUInt16(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为32位有符号整数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected int ConvertToInt32(object v, int DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToInt32(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为32位无符号整数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected uint ConvertToUInt32(object v, uint DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToUInt32(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为64位有符号整数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected long ConvertToInt64(object v, long DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToInt64(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为64位无符号整数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected ulong ConvertToUInt64(object v, ulong DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToUInt64(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为小数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected decimal ConvertToDecimal(object v, decimal DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToDecimal(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为单精度浮点数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected float ConvertToSingle(object v, float DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToSingle(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为双精度浮点数，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected double ConvertToDouble(object v, double DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToDouble(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为时间数据，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <param name="Format">时间数据解析格式</param>
        /// <returns>转换后的数值</returns>
        protected DateTime ConvertToDateTime(object v, DateTime DefaultValue, string Format)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            if (v is DateTime)
                return (DateTime)v;
            if (Format != null || Format.Length > 0)
            {
                string str = Convert.ToString(v);
                return DateTime.ParseExact(str, Format, null);
            }
            return Convert.ToDateTime(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为字符串，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected string ConvertToString(object v, string DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToString(v);
        }

        /// <summary>
        /// 将从数据库获得的原始数据转换为字符，若数值为空则返回默认值
        /// </summary>
        /// <param name="v">从数据库获得的原始数据</param>
        /// <param name="DefaultValue">默认值</param>
        /// <returns>转换后的数值</returns>
        protected char ConvertToChar(object v, char DefaultValue)
        {
            if (v == null || DBNull.Value.Equals(v))
                return DefaultValue;
            else
                return Convert.ToChar(v);
        }

        #endregion

        /// <summary>
        /// 将日期数据转换为数据库中的格式,本函数会在动态生成的派生类中使用.
        /// </summary>
        /// <param name="Value">日期数据</param>
        /// <param name="Format">保存格式化字符串</param>
        /// <returns>转换后的数据</returns>
        protected object DateTimeToDBValue(DateTime Value, string Format)
        {
            if (Format != null || Format.Length > 0)
            {
                return Value.ToString(Format);
            }
            else
            {
                return Value;
            }
        }

    }//public abstract class RecordORMHelper
}